package dnl.dtools.grm;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.google.inject.Inject;

import dnl.dtools.grm.operations.SimpleResourceOperation;
import dnl.dtools.grm.operations.TargetBasedResourceOperation;
import dnl.dtools.grm.operations.io.LocalFsCopyOperation;
import dnl.dtools.grm.operations.io.LocalFsDeleteOperation;
import dnl.dtools.grm.remote.RemoteSessionsManager;
import dnl.dtools.grm.remote.UserPasswordRemoteSessionInfo;
import dnl.dtools.grm.security.PasswordRegistry;
import dnl.dtools.grm.ssh.GanymedSshEntry;
import dnl.dtools.grm.ssh.SshSession;
import dnl.logging.LightLog;


public class GenericResourceOperations {

	public enum OperationType {COPY, MOVE, DELETE};

	private RemoteSessionsManager sessionsManager;
	private PasswordRegistry passwordManager;
	private Resource cachedSemanticRoot;
	
	@Inject
	public GenericResourceOperations(RemoteSessionsManager sessionsManager, PasswordRegistry passwordManager) {
		super();
		this.sessionsManager = sessionsManager;
		this.passwordManager = passwordManager;
	}

	public Resource getSemanticRoot(){
		if(cachedSemanticRoot == null){
			Collection<UserPasswordRemoteSessionInfo> allRegisteredSessions = sessionsManager.getAllRegisteredSessions();
			List<SessionResource> sessions = new ArrayList<SessionResource>();
			for (UserPasswordRemoteSessionInfo info : allRegisteredSessions) {
				SessionResource sr = new SessionResource(null, info);
				sessions.add(sr);
			}
			
			try {
				cachedSemanticRoot = new SemanticResource(new URL("semantic://root"), "root", listRoots(), null);
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
		}
		return cachedSemanticRoot;
	}
	
	public Resource getResourceForUrl(URL url) throws URISyntaxException{
		String protocol = url.getProtocol();
		if(protocol.startsWith("scp")){
			String userName = url.getUserInfo();
			String hostName = url.getHost();
			UserPasswordRemoteSessionInfo sshSessionInfo = sessionsManager.getRegisteredSession(hostName, userName);
			if(sshSessionInfo == null){
				LightLog.error("No session info.");
				return null;
			}
			SshSession sshSession = new SshSession(sshSessionInfo);
			sshSession.setPasswordManager(passwordManager);
			return new GanymedSshEntry(url, sshSession);
		}
		if(protocol.startsWith("semantic")){
			return getSemanticRoot();
		}
		return new LocalFileSystemEntry(url);
	}
	
	private Resource[] listRoots() {
		File[] roots = File.listRoots();
		List<Resource> drives = new ArrayList<Resource>();

//		for (int i = 0; i < roots.length; i++) {
//			//ResourceAlias alias = new ResourceAlias(LocalFileSystemEntry.from(roots[i]), roots[i].getName());
//			Resource r = LocalFileSystemEntry.from(roots[i]);
//			drives.add(r);
//		}
//
//		String userHome = System.getProperty("user.home");
//		if (userHome != null) {
//			File userHomeF = new File(userHome);
//			ResourceAlias alias = new ResourceAlias(LocalFileSystemEntry.from(userHomeF), "User Home");
//			drives.add(alias);
//		}
//
//		// if we run in a Unix flavored system
//		// we will have /mnt
//		File mnt = new File("/mnt");
//		if (mnt.exists()) {
//			File[] mounts = mnt.listFiles();
//
//			for (int i = 0; i < mounts.length; i++) {
//				drives.add(LocalFileSystemEntry.from(mounts[i]));
//			}
//
//		}
		return drives.toArray(new Resource[drives.size()]);
	}
	
	public TargetBasedResourceOperation getTargetBasedResourceOperation(OperationType op,
			Resource[] sources, Resource target) {
		switch (op) {
		case COPY:
//			if(!hasAtLeastOneDir(sources)){
//				return new GenericCopyOperation(sources, target);
//			}
			return new LocalFsCopyOperation(sources, target);
		case MOVE:
			break;

		}
		return null;
	}

	public SimpleResourceOperation getResourceOperation(OperationType op,
			Resource[] sources) {
		switch (op) {
		case DELETE:
			return new LocalFsDeleteOperation(sources);
		}
		return null;
	}
	
}
